﻿// -------------------------------------------------------------------------
//    @FileName         :    PerformanceTest.cpp
//    @Author           :    gaoyi
//    @Date             :    2025/1/20
//    @Email            :    445267987@qq.com
//    @Module           :    PerformanceTest
//
// -------------------------------------------------------------------------

#include "BagSystemTestBase.h"
#include "MockItemDesc.h"
#include <chrono>
#include <algorithm>
#include <thread>

/**
 * @brief 性能测试类
 * 
 * 测试背包系统的性能指标：
 * - 大批量物品操作性能
 * - 查找和搜索性能
 * - 内存使用效率
 * - 并发性能
 * - 操作时间复杂度验证
 */
class PerformanceTest : public BagSystemTestBase {
protected:
    void SetUp() override {
        BagSystemTestBase::SetUp();
        m_testPlayer = CreateTestPlayer();
        m_startTime = std::chrono::high_resolution_clock::now();
    }
    
    void TearDown() override {
        m_testPlayer = nullptr;
        BagSystemTestBase::TearDown();
    }
    
    /**
     * @brief 开始性能计时
     */
    void StartTimer() {
        m_startTime = std::chrono::high_resolution_clock::now();
    }
    
    /**
     * @brief 结束性能计时并返回耗时（毫秒）
     */
    double EndTimer() {
        auto endTime = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endTime - m_startTime);
        return duration.count() / 1000.0; // 转换为毫秒
    }
    
    /**
     * @brief 验证操作性能是否在合理范围内
     */
    void AssertPerformance(double actualMs, double expectedMaxMs, const std::string& operation) {
        ASSERT_LE(actualMs, expectedMaxMs) 
            << operation << " 操作耗时 " << actualMs << "ms 超过预期最大值 " << expectedMaxMs << "ms";
    }

protected:
    NFPlayer* m_testPlayer;
    std::chrono::high_resolution_clock::time_point m_startTime;
    
    // 性能基准常量
    static constexpr double MAX_SINGLE_ADD_TIME_MS = 1.0;      // 单次添加最大耗时
    static constexpr double MAX_BATCH_ADD_TIME_MS = 100.0;     // 批量添加最大耗时
    static constexpr double MAX_SEARCH_TIME_MS = 5.0;          // 搜索最大耗时
    static constexpr double MAX_DELETE_TIME_MS = 10.0;         // 删除最大耗时
    static constexpr int PERFORMANCE_TEST_ITEM_COUNT = 1000;   // 性能测试物品数量
    static constexpr int LARGE_BATCH_SIZE = 10000;             // 大批量操作数量
};

// === 基础操作性能测试 ===

/**
 * @brief 测试单次物品添加性能
 */
TEST_F(PerformanceTest, SingleItemAddPerformanceTest) {
    const int testCount = 100;
    double totalTime = 0;
    
    for (int i = 0; i < testCount; ++i) {
        StartTimer();
        int result = NFServicePackage::AddByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, 1);
        double elapsed = EndTimer();
        totalTime += elapsed;
        
        ASSERT_EQ(result, 0) << "第" << i << "次添加物品失败";
    }
    
    double averageTime = totalTime / testCount;
    AssertPerformance(averageTime, MAX_SINGLE_ADD_TIME_MS, "单次物品添加");
    
    std::cout << "单次物品添加平均耗时: " << averageTime << "ms" << std::endl;
}

/**
 * @brief 测试批量物品添加性能
 */
TEST_F(PerformanceTest, BatchItemAddPerformanceTest) {
    const int batchSize = 100;
    
    // 创建批量添加数据
    std::vector<WillAddItemData> willAddItems;
    for (int i = 0; i < batchSize; ++i) {
        WillAddItemData willAdd;
        willAdd.itemId = TestItemIds::NORMAL_ITEM_1 + (i % 10);
        willAdd.count = 1;
        willAdd.quality = TestQuality::WHITE;
        willAdd.bind = false;
        willAddItems.push_back(willAdd);
    }
    
    NFBagPageOpMgr* opMgr = CreateTestBagOpMgr(m_testPlayer, TEST_REASON_SYSTEM, true);
    
    StartTimer();
    for (const auto& willAdd : willAddItems) {
        int result = opMgr->AddToBag(willAdd, 1, nullptr);
        ASSERT_EQ(result, 0) << "批量添加物品失败";
    }
    opMgr->Commit();
    double elapsed = EndTimer();
    
    AssertPerformance(elapsed, MAX_BATCH_ADD_TIME_MS, "批量物品添加");
    
    std::cout << "批量添加" << batchSize << "个物品耗时: " << elapsed << "ms" << std::endl;
}

/**
 * @brief 测试物品搜索性能
 */
TEST_F(PerformanceTest, ItemSearchPerformanceTest) {
    // 先添加一些物品
    const int itemCount = 50;
    for (int i = 0; i < itemCount; ++i) {
        NFServicePackage::AddByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1 + i, 1);
    }
    
    // 测试搜索性能
    const int searchCount = 100;
    double totalTime = 0;
    
    for (int i = 0; i < searchCount; ++i) {
        int searchItemId = TestItemIds::NORMAL_ITEM_1 + (i % itemCount);
        
        StartTimer();
        int count = 0;
        NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, searchItemId, count);
        double elapsed = EndTimer();
        totalTime += elapsed;
        
        ASSERT_EQ(count, 1) << "搜索物品数量不正确";
    }
    
    double averageTime = totalTime / searchCount;
    AssertPerformance(averageTime, MAX_SEARCH_TIME_MS, "物品搜索");
    
    std::cout << "物品搜索平均耗时: " << averageTime << "ms" << std::endl;
}

/**
 * @brief 测试物品删除性能
 */
TEST_F(PerformanceTest, ItemDeletePerformanceTest) {
    // 先添加大量物品
    const int itemCount = 100;
    for (int i = 0; i < itemCount; ++i) {
        NFServicePackage::AddByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1 + i, 1);
    }
    
    // 测试删除性能
    StartTimer();
    for (int i = 0; i < itemCount; ++i) {
        int result = NFServicePackage::DelItemByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1 + i, 1, nullptr);
        ASSERT_EQ(result, 0) << "删除物品失败";
    }
    double elapsed = EndTimer();
    
    AssertPerformance(elapsed, MAX_DELETE_TIME_MS, "批量删除");
    
    std::cout << "批量删除" << itemCount << "个物品耗时: " << elapsed << "ms" << std::endl;
}

// === 大规模数据性能测试 ===

/**
 * @brief 测试大规模物品操作性能
 */
TEST_F(PerformanceTest, LargeScaleOperationTest) {
    const int largeItemCount = PERFORMANCE_TEST_ITEM_COUNT;
    
    // 测试大规模添加
    StartTimer();
    NFBagPageOpMgr* opMgr = CreateTestBagOpMgr(m_testPlayer, TEST_REASON_SYSTEM, true);
    
    int addedCount = 0;
    for (int i = 0; i < largeItemCount && addedCount < 100; ++i) {
        WillAddItemData willAdd;
        willAdd.itemId = TestItemIds::NORMAL_ITEM_1 + (i % 50);
        willAdd.count = 1;
        willAdd.quality = TestQuality::WHITE;
        willAdd.bind = false;
        
        int result = opMgr->AddToBag(willAdd, 1, nullptr);
        if (result == 0) {
            addedCount++;
        } else {
            // 背包满了，停止添加
            break;
        }
    }
    
    opMgr->Commit();
    double addTime = EndTimer();
    
    std::cout << "大规模添加" << addedCount << "个物品耗时: " << addTime << "ms" << std::endl;
    
    // 测试大规模搜索
    StartTimer();
    int totalFoundItems = 0;
    for (int i = 0; i < 50; ++i) {
        int count = 0;
        NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::NORMAL_ITEM_1 + i, count);
        totalFoundItems += count;
    }
    double searchTime = EndTimer();
    
    std::cout << "大规模搜索50种物品耗时: " << searchTime << "ms, 找到" << totalFoundItems << "个物品" << std::endl;
    
    // 性能断言
    ASSERT_LE(addTime, 500.0) << "大规模添加操作耗时过长";
    ASSERT_LE(searchTime, 50.0) << "大规模搜索操作耗时过长";
}

/**
 * @brief 测试堆叠物品操作性能
 */
TEST_F(PerformanceTest, StackableItemPerformanceTest) {
    const int stackOperations = 200;
    
    // 测试堆叠操作性能
    StartTimer();
    for (int i = 0; i < stackOperations; ++i) {
        int result = NFServicePackage::AddByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::STACKABLE_ARROW, 10);
        ASSERT_EQ(result, 0) << "堆叠物品添加失败";
    }
    double elapsed = EndTimer();
    
    std::cout << "堆叠物品操作" << stackOperations << "次耗时: " << elapsed << "ms" << std::endl;
    
    // 验证最终堆叠结果
    int totalCount = 0;
    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::STACKABLE_ARROW, totalCount);
    ASSERT_EQ(totalCount, stackOperations * 10) << "堆叠物品数量不正确";
    
    AssertPerformance(elapsed, 100.0, "堆叠物品操作");
}

// === 复杂操作性能测试 ===

/**
 * @brief 测试复杂混合操作性能
 */
TEST_F(PerformanceTest, ComplexMixedOperationTest) {
    const int operationCount = 100;
    
    // 初始化一些物品
    for (int i = 0; i < 20; ++i) {
        NFServicePackage::AddByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1 + i, 5);
    }
    
    StartTimer();
    
    // 执行混合操作：添加、删除、搜索、修改
    for (int i = 0; i < operationCount; ++i) {
        int operation = i % 4;
        int itemId = TestItemIds::NORMAL_ITEM_1 + (i % 10);
        
        switch (operation) {
            case 0: // 添加
                NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, itemId, 1);
                break;
            case 1: // 删除
                NFServicePackage::DelItemByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, itemId, 1, nullptr);
                break;
            case 2: // 搜索
                {
                    int count = 0;
                    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, itemId, count);
                }
                break;
            case 3: // 获取物品
                {
                    std::vector<NFGridItem> items;
                    NFServicePackage::GetBagItemByItemID(m_testPlayer, itemId, items);
                }
                break;
        }
    }
    
    double elapsed = EndTimer();
    
    std::cout << "混合操作" << operationCount << "次耗时: " << elapsed << "ms" << std::endl;
    AssertPerformance(elapsed, 200.0, "复杂混合操作");
}

/**
 * @brief 测试事务操作性能
 */
TEST_F(PerformanceTest, TransactionOperationPerformanceTest) {
    const int transactionCount = 50;
    const int operationsPerTransaction = 10;
    
    StartTimer();
    
    for (int t = 0; t < transactionCount; ++t) {
        NFBagPageOpMgr* opMgr = CreateTestBagOpMgr(m_testPlayer, TEST_REASON_SYSTEM, true);
        
        // 每个事务执行多个操作
        for (int i = 0; i < operationsPerTransaction; ++i) {
            WillAddItemData willAdd;
            willAdd.itemId = TestItemIds::NORMAL_ITEM_1 + (i % 5);
            willAdd.count = 1;
            willAdd.quality = TestQuality::WHITE;
            willAdd.bind = false;
            
            int result = opMgr->AddToBag(willAdd, 1, nullptr);
            if (result != 0) {
                // 背包满了，跳过
                break;
            }
        }
        
        opMgr->Commit();
    }
    
    double elapsed = EndTimer();
    
    std::cout << "事务操作" << transactionCount << "次耗时: " << elapsed << "ms" << std::endl;
    AssertPerformance(elapsed, 300.0, "事务操作");
}

// === 内存使用效率测试 ===

/**
 * @brief 测试内存使用效率
 */
TEST_F(PerformanceTest, MemoryEfficiencyTest) {
    const int itemCount = 500;
    
    // 获取初始内存使用情况（简化版本，实际应该使用内存分析工具）
    size_t initialMemoryUsage = 0; // 这里应该获取实际内存使用量
    
    StartTimer();
    
    // 添加大量物品
    std::vector<int> addedItems;
    for (int i = 0; i < itemCount; ++i) {
        int itemId = TestItemIds::NORMAL_ITEM_1 + (i % 50);
        int result = NFServicePackage::AddByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, itemId, 1);
        if (result == 0) {
            addedItems.push_back(itemId);
        } else {
            // 背包满了，停止添加
            break;
        }
    }
    
    double addTime = EndTimer();
    
    // 清理内存
    StartTimer();
    for (int itemId : addedItems) {
        NFServicePackage::DelItemByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, itemId, 1, nullptr);
    }
    double cleanupTime = EndTimer();
    
    std::cout << "内存效率测试 - 添加" << addedItems.size() << "个物品耗时: " << addTime << "ms" << std::endl;
    std::cout << "内存效率测试 - 清理" << addedItems.size() << "个物品耗时: " << cleanupTime << "ms" << std::endl;
    
    // 验证内存是否正确释放
    int remainingItems = 0;
    for (int i = 0; i < 50; ++i) {
        int count = 0;
        NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::NORMAL_ITEM_1 + i, count);
        remainingItems += count;
    }
    
    ASSERT_EQ(remainingItems, 0) << "清理后仍有物品残留";
}

// === 并发性能测试 ===

/**
 * @brief 测试并发操作性能（模拟）
 */
TEST_F(PerformanceTest, ConcurrentOperationPerformanceTest) {
    const int concurrentOperations = 10;
    
    StartTimer();
    
    // 模拟并发操作（实际上是顺序执行，真正的并发测试需要多线程）
    std::vector<NFBagPageOpMgr*> managers;
    for (int i = 0; i < concurrentOperations; ++i) {
        NFBagPageOpMgr* opMgr = CreateTestBagOpMgr(m_testPlayer, TEST_REASON_SYSTEM, true);
        managers.push_back(opMgr);
        
        WillAddItemData willAdd;
        willAdd.itemId = TestItemIds::NORMAL_ITEM_1 + i;
        willAdd.count = 1;
        willAdd.quality = TestQuality::WHITE;
        willAdd.bind = false;
        
        int result = opMgr->AddToBag(willAdd, 1, nullptr);
        if (result != 0) {
            // 背包满了，跳过
            continue;
        }
    }
    
    // 提交所有操作
    for (auto* mgr : managers) {
        mgr->Commit();
    }
    
    double elapsed = EndTimer();
    
    std::cout << "并发操作" << concurrentOperations << "次耗时: " << elapsed << "ms" << std::endl;
    AssertPerformance(elapsed, 100.0, "并发操作");
}

// === 性能基准测试 ===

/**
 * @brief 测试系统性能基准
 */
TEST_F(PerformanceTest, PerformanceBenchmarkTest) {
    const int benchmarkOperations = 1000;
    
    std::cout << "\n=== 背包系统性能基准测试 ===" << std::endl;
    
    // 1. 基础添加操作基准
    StartTimer();
    int addedCount = 0;
    for (int i = 0; i < benchmarkOperations && addedCount < 100; ++i) {
        int result = NFServicePackage::AddByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1 + (i % 10), 1);
        if (result == 0) {
            addedCount++;
        } else {
            break;
        }
    }
    double addBenchmark = EndTimer();
    
    // 2. 搜索操作基准
    StartTimer();
    for (int i = 0; i < 100; ++i) {
        int count = 0;
        NFServicePackage::GetBagItemTotalNumByItemID(
            m_testPlayer, TestItemIds::NORMAL_ITEM_1 + (i % 10), count);
    }
    double searchBenchmark = EndTimer();
    
    // 3. 删除操作基准
    StartTimer();
    for (int i = 0; i < addedCount; ++i) {
        NFServicePackage::DelItemByItemIDAndNum(
            m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1 + (i % 10), 1, nullptr);
    }
    double deleteBenchmark = EndTimer();
    
    // 输出基准结果
    std::cout << "添加操作基准: " << addedCount << "个物品耗时 " << addBenchmark << "ms" << std::endl;
    std::cout << "搜索操作基准: 100次搜索耗时 " << searchBenchmark << "ms" << std::endl;
    std::cout << "删除操作基准: " << addedCount << "个物品耗时 " << deleteBenchmark << "ms" << std::endl;
    
    // 计算性能指标
    double addOpsPerSecond = (addedCount * 1000.0) / addBenchmark;
    double searchOpsPerSecond = (100.0 * 1000.0) / searchBenchmark;
    double deleteOpsPerSecond = (addedCount * 1000.0) / deleteBenchmark;
    
    std::cout << "性能指标:" << std::endl;
    std::cout << "  添加操作: " << addOpsPerSecond << " ops/sec" << std::endl;
    std::cout << "  搜索操作: " << searchOpsPerSecond << " ops/sec" << std::endl;
    std::cout << "  删除操作: " << deleteOpsPerSecond << " ops/sec" << std::endl;
    
    // 性能断言
    ASSERT_GT(addOpsPerSecond, 100.0) << "添加操作性能过低";
    ASSERT_GT(searchOpsPerSecond, 1000.0) << "搜索操作性能过低";
    ASSERT_GT(deleteOpsPerSecond, 100.0) << "删除操作性能过低";
} 